home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / tpu55a.zip / TPUUNA1.PAS < prev   
Pascal/Delphi Source File  |  1990-08-06  |  24KB  |  949 lines

  1. UNIT TPUUNA1;
  2.  
  3. (*****************)
  4. (**) INTERFACE (**)
  5. (*****************)
  6. USES TPUAMS1;
  7.  
  8. TYPE
  9.     OprStr = String[32];
  10.  
  11.     CpuGate = (C086,C186,C286,C386);
  12.  
  13.     ObjArg =
  14.         RECORD
  15.             Obj  : Word;    { Offset of text to Unassemble }
  16.             Lim  : Word;    { Max Bytes to Examine  }
  17.             TCpu : CpuGate; { Cpu code to handle }
  18.             Locn : Word;    { Code Offset }
  19.             Code : OprStr;    { Object Text in ASCII }
  20.             Mnem : OprStr;    { Mnemonic(s) in ASCII }
  21.             Opr1 : OprStr;    { ASCII Operand 1 }
  22.             Opr2 : OprStr;    { ASCII Operand 2 }
  23.             Opr3 : OprStr;    { ASCII Operand 3 }
  24.         END;
  25.  
  26. CONST    SegDBit : Boolean = FALSE; { Assume 16-Bit Addressing }
  27.  
  28. PROCEDURE UnAssemble(U : UnitHeadPtr; VAR P : ObjArg);
  29.  
  30. (**********************)
  31. (**) IMPLEMENTATION (**)
  32. (**********************)
  33.  
  34. TYPE    { Types Below Used For Quick Classification of Op-Codes }
  35.  
  36.    Gating =
  37.     (G_RM1,     G_RM2,     G_RM3,     G_RM4,     G_RM5,
  38.      G_RM6,     G_RM7,     G_RM8,     G_RM9,        { modR/M Has op bits }
  39.      G_Hit,    { defined operation }
  40.      G_0Fx,    { 0F-type operation }
  41.      G_387,    { escapes to 80387  }
  42.      G_Pfx,    { prefix  operation }
  43.      G_ooo);   { invalid operation }
  44.  
  45.    Gate_2 =        { 2nd-level gates for G_0Fx Operations }
  46.     (Row_0,
  47.      Row_2,
  48.      Row_8,
  49.      Row_9,
  50.      Row_A,
  51.      Row_B,
  52.      Row_X);   { invalid otherwise }
  53.  
  54.    TAdr = (Adr16,Adr32);    {16-bit or 32-bit Addressing}
  55.    WBitStatus = (W0,W1);    {W1 = W-bit ON, else W0}
  56.    REGString = String[3];
  57.    TagRec =
  58.     RECORD
  59.         A : Char;    {tells type of operand}
  60.         V : Byte        {gives width/value etc}
  61.     END;
  62.    TagGrp = ARRAY[1..3] OF TagRec;
  63.  
  64.    CpuVec =
  65.     RECORD
  66.         F,    {Bit Flags for Processing Options}
  67.             {1xxx xxxx = alternate Mnemonic at M+1  }
  68.             {x1xx xxxx = 32-bit if OpSiz Prefix     }
  69.             {xx1x xxxx = 16-bit normally            }
  70.             {xxx1 xxxx = sign-extend immediates     }
  71.             {xxxx 1xxx = Op has modR/M field        }
  72.             {---- -ccc = Cpu Required for Op    }
  73.  
  74.         M,    {8086  Mnemonic Index}
  75.         T    {Operand Format Index}
  76.                             : Byte
  77.     END;
  78.  
  79.    MpuVec =                    {.CP27}
  80.     RECORD
  81.         F,    { Flag Bits (see below)
  82.             0000 0000 = INVALID operation
  83.             0010 xxxx = Entire modR/M byte defines op-code
  84.             0001 xxxx = modR/M REG field defines op-code
  85.  
  86.             xxxx 0000 = no explicit operand(s) coded
  87.             xxxx 0001 = operand is "AX"
  88.             xxxx 0010 = operand is "Bcd80"
  89.             xxxx 0011 = operand is "Ea" (no size implied)
  90.             xxxx 0100 = operand is "Ew" (16-bit word)
  91.             xxxx 0101 = operand is "Int16"
  92.             xxxx 0110 = operand is "Int32"
  93.             xxxx 0111 = operand is "Int64"
  94.             xxxx 1000 = operand is "Real32"
  95.             xxxx 1001 = operand is "Real64"
  96.             xxxx 1010 = operand is "Real80"
  97.             xxxx 1011 = operand is "ST(i)"
  98.             xxxx 1100 = operand is "ST(i),ST"
  99.             xxxx 1101 = operand is "ST,ST(i)"
  100.             xxxx 1110 = reserved
  101.             xxxx 1111 = reserved
  102.             }
  103.         M    { index to mnemonic table }
  104.                 : Byte
  105.     END;
  106.  
  107.  
  108.    TMrm =
  109.     RECORD
  110.         D,       { Size in Bytes of Displacement Field}
  111.         SIB,     { 1 -> SIB field present, else no SIB}
  112.         rS,      { index to Segment Register String   }
  113.         rB,      { index to  Base   Register String   }
  114.         rX       { index to  Index  Register String   }
  115.             : Byte
  116.     END;
  117.  
  118.    SibRec =
  119.     RECORD
  120.         D,      { displacement width (bytes) }
  121.         rS,     { default segment register   }
  122.         rB      { default base register      }
  123.             : Byte
  124.     END;
  125.  
  126.    sxRec =
  127.     RECORD
  128.         rX,  { to index reg name }
  129.         sF   { multiplier; if 0, ss must be too or illegal}
  130.             : Byte
  131.     END;
  132. {$I TPUUNA1.INC}
  133.  
  134. VAR                                    {.CP32}
  135.     Is_386Xtnsn,    Is_32BitMax,    Is_16BitMin,    Is_SignXtnd,
  136.     Is_MODrmFld,    HaveSizePfx,    HaveAddrPfx,    HaveMRM,
  137.     HaveSIB,    FetchFailure,    DSiz32,        ASiz32,
  138.     HaveSegPfx,    HaveInstPfx,    HaveMemOprnd    : Boolean;
  139.  
  140.     CpuAuth        : CpuGate;
  141.  
  142.     CodeByte,    PfxMax,        OprBytes,    DataByte,
  143.     DLoc,        mrmMOD,        mrmREG,        mrmRM,
  144.     IPfx,        sibSS,        sibNDX,        sibBAS,
  145.     EmuFlag,    SPfx                    : Byte;
  146.  
  147.     BytesFetched,    BytesRemaining,    PrefixBytes,    CodeSeg,
  148.     CodeOfs,    VirtualIP                : Word;
  149.  
  150.     REGOperand,    REGSeg,        REGBase,
  151.     REGIndex,    REGSegOvr            : REGString;
  152.  
  153.     EAOperand,    CodeText,    Mnemonic    : OprStr;
  154.  
  155.     CodeStack    : ARRAY[1..16] OF Byte;
  156.     Opnd         : ARRAY[1..3]  OF OprStr;
  157.     ActGroup    : CpuVec;
  158.     OpTags        : TagGrp;
  159.     NdxSF        : String[2];
  160.  
  161.     ByteGate    : Gating;
  162.     AddrMode    : TAdr;
  163.     WBitMode    : WBitStatus;
  164.  
  165.     { --------------------------------------------- } {.CP19}
  166.     { Fetches a Byte and stacks it for Disassembler }
  167.     { --------------------------------------------- }
  168.  
  169. FUNCTION FetchByte : Byte;
  170. BEGIN
  171.     FetchFailure := BytesRemaining = 0;
  172.     IF NOT FetchFailure THEN
  173.     BEGIN
  174.         Inc(BytesFetched);
  175.         {$R+}
  176.         CodeStack[BytesFetched] := Mem[CodeSeg:CodeOfs];
  177.         {$R-}
  178.         Dec(BytesRemaining);
  179.         Inc(CodeOfs);
  180.     END;
  181.         FetchByte := CodeStack[BytesFetched]
  182. END;
  183.  
  184.     { ----------------------------------------------- } {.CP14}
  185.     { Undoes the Fetch Byte Process - Pops From Stack }
  186.     { ----------------------------------------------- }
  187.  
  188. PROCEDURE UnFetchCodeByte;
  189. BEGIN
  190.     IF BytesFetched > 0 THEN
  191.     BEGIN
  192.         Dec(BytesFetched);
  193.         Inc(BytesRemaining);
  194.         Dec(CodeOfs);
  195.     END
  196. END;
  197.  
  198.     { ------------------------------------------------- } {.CP13}
  199.     { Formats a Sequence of Stacked Bytes as printable  }
  200.     { Hex in "logical" order - not processor order, and }
  201.     { appends a Padding String and a Blank            }
  202.     { ------------------------------------------------- }
  203.  
  204. PROCEDURE FormatText(Locn, SLen:Byte; Pad : String);
  205. VAR  W : OprStr; i : Byte;
  206. BEGIN
  207.     W := '';
  208.     FOR i := Locn TO Locn+SLen-1 DO W := HexB(CodeStack[i]) + W;
  209.     CodeText := CodeText + W + Pad + ' ';
  210. END;
  211.  
  212.     { ------------------- }    {.CP11}
  213.     { Unpacks modR/M Byte }
  214.     { ------------------- }
  215.  
  216. PROCEDURE UnPackModRM(modRM : Byte);
  217. BEGIN
  218.     HaveMRM := True;
  219.     mrmMOD := (modRM SHR 6) AND $03;
  220.     mrmREG := (modRM SHR 3) AND $07;
  221.     mrmRM  :=  modRM AND $07;
  222. END;
  223.  
  224.     { ---------------- } {.CP11}
  225.     { Unpacks SIB Byte }
  226.     { ---------------- }
  227.  
  228. PROCEDURE UnPackSIB(sib : Byte);
  229. BEGIN
  230.     HaveSIB := True;
  231.     sibSS   := (sib SHR 6) AND $03;
  232.     sibNDX  := (sib SHR 3) AND $07;
  233.     sibBAS  :=  sib AND $07;
  234. END;
  235.  
  236. PROCEDURE MergeActGrp(VAR Z : CpuVec);                {.CP10}
  237. VAR I,J : Byte;
  238. BEGIN
  239.     ActGroup.M := Z.M;
  240.     IF Z.T <> 0 THEN ActGroup.T := Z.T;
  241.     I := ActGroup.F AND $7;
  242.     J := Z.F AND $7;
  243.     IF I < J THEN I := J;
  244.     ActGroup.F := ((ActGroup.F OR Z.F) AND $F8) OR I;
  245. END;
  246.  
  247.     { ------------------------------------------------- } {.CP52}
  248.     { Formats a Sequence of Stacked Bytes as printable  }
  249.     { Hex in "logical" order - not processor order for  }
  250.     { use in Operand Expressions.  Lead zero suppressed }
  251.     { May be SIGNED or UN-SIGNED                        }
  252.     { ------------------------------------------------- }
  253.  
  254. PROCEDURE FormatDispl(VAR Sx:OprStr; Locn, SLen:Byte; Signed:Boolean);
  255. TYPE
  256.   MyWord = RECORD
  257.     CASE Byte OF
  258.         0: (Ds : ShortInt);
  259.         1: (Db : Byte);
  260.         2: (Dw : Word);
  261.         3: (Di : Integer);
  262.         4: (Dd : LongInt);
  263.         5: (Dv : ARRAY[1..4] OF Byte);
  264.     END;
  265.  
  266. VAR    W, X : MyWord; I : Byte; P : ^MyWord; Signit : Char;
  267. BEGIN
  268.     Sx := '';
  269.     IF SLen IN [1,2,4] THEN
  270.     BEGIN
  271.         P := @ CodeStack[Locn];
  272.         W.Dd := 0; X := W;
  273.         WITH P^ DO
  274.         IF Signed THEN
  275.         BEGIN            { sign extend for next step }
  276.             CASE SLen OF
  277.                 1: W.Dd := Ds;
  278.                 2: W.Dd := Di;
  279.                 4: W.Dd := Dd
  280.             END;
  281.             X.Dd := Abs(W.Dd)
  282.         END ELSE
  283.         BEGIN            { zero extend for next step }
  284.             CASE SLen OF
  285.                 1: W.Dd := Db;
  286.                 2: W.Dd := Dw;
  287.                 4: W.Dd := Dd
  288.             END;
  289.             X.Dd := W.Dd
  290.         END;
  291.         FOR i := 1 TO SLen DO Sx := HexB(X.Dv[i]) + Sx;
  292.         IF X.Dd <> W.Dd
  293.             THEN Signit := '-'
  294.             ELSE Signit := '+';
  295.         Sx := Sx + 'h';
  296.         IF Signed THEN Sx := Signit + Sx;
  297.     END;
  298. END; {FormatDispl}
  299.  
  300.     { ------------------------------------ }  {.CP24}
  301.     { ERROR - Stacked Code printed as DB's }
  302.     { ------------------------------------ }
  303.  
  304. PROCEDURE EmitConstants;
  305. VAR c : Char;
  306. BEGIN
  307.     WHILE BytesFetched > 1 DO UnFetchCodeByte;
  308.     Mnemonic := 'DB';
  309.     CodeText := '';
  310.     HaveInstPfx := False;
  311.     c := Char(CodeStack[1]);
  312.     CodeText := HexB(Byte(c));
  313.     CASE c OF
  314.         ' '..'&',
  315.         '('..#$7F:    Opnd[1] := '''' + c + '''';
  316.         ELSE        Opnd[1] := '0' + CodeText + 'h';
  317.     END;
  318.     Opnd[2] := '';
  319.     Opnd[3] := '';
  320.     { Ready to Build and Print Line }
  321. END;
  322.  
  323.     { --------------------- } {.CP08}
  324.     { Returns Register Name }
  325.     { --------------------- }
  326.  
  327. FUNCTION ExtractReg(Am : TAdr; Wbit : WBitStatus; Arg : Byte) : RegString;
  328. BEGIN
  329.     ExtractReg := RegList[RegDecode[Am,Wbit,Arg]]
  330. END;
  331.  
  332.     { ----------------------------------- } {.CP12}
  333.     { Fetches Displacement/Immediate Data }
  334.     { ----------------------------------- }
  335.  
  336. FUNCTION FetchDispl(Width:Byte) : Byte; { Index to LSB of Displ }
  337. VAR i, j : Byte;
  338. BEGIN
  339.     FOR i := 1 TO Width DO j := FetchByte;
  340.     IF FetchFailure
  341.         THEN FetchDispl := 0
  342.         ELSE FetchDispl := BytesFetched + 1 - Width;
  343. END;
  344.  
  345.     { ------------------------------- } {.CP05}
  346.     { Decodes and Stacks Prefix Bytes }
  347.     { ------------------------------- }
  348.  
  349. PROCEDURE HandlePrefix;
  350.  
  351.     PROCEDURE StowPrefix;                             {.CP45}
  352.     CONST PfxFlg : ARRAY[1..4] OF CHAR = '>||:';
  353.     VAR PfxCls : 1..4; i : Byte;
  354.     BEGIN
  355.         CASE CodeByte OF
  356.            $F0,    $F2..$F3:    BEGIN    {LOCK/REPE/REPNE}
  357.                         PfxCls := 1;
  358.                         IPfx := CodeByte;
  359.                         HaveInstPfx := True;
  360.                     END;
  361.             $67:        BEGIN   {Address Size Prefix}
  362.                         PfxCls := 2;
  363.                         ASiz32 := NOT SegDBit;
  364.                         HaveAddrPfx := True;
  365.                     END;
  366.             $66:        BEGIN   {Operand Size Prefix}
  367.                         PfxCls := 3;
  368.                         DSiz32 := NOT SegDBit;
  369.                         HaveSizePfx := True;
  370.                     END;
  371.             $26,$2E,
  372.             $36,$3E:    BEGIN   {Segment Prefix ES,CS,SS,DS}
  373.                         PfxCls := 4;
  374.                         SPfx := BytesFetched;
  375.                         HaveSegPfx := True;
  376.                         i := CodeByte SHR 3 AND $03;
  377.                         REGSegOvr := RegList[i + 24];
  378.                     END;
  379.             $64,$65:    BEGIN   {Segment Prefix FS,GS}
  380.                         PfxCls := 4;
  381.                         SPfx := BytesFetched;
  382.                         HaveSegPfx := True;
  383.                         i := CodeByte AND $07;
  384.                         REGSegOvr := RegList[i + 24];
  385.                     END;
  386.         END;
  387.         IF PfxCls > PfxMax THEN
  388.         BEGIN
  389.             Inc(PrefixBytes);
  390.             PfxMax := PfxCls;
  391.             FormatText(BytesFetched,1,PfxFlg[PfxCls]);
  392.         END ELSE
  393.         BEGIN
  394.             UnFetchCodeByte;   { will fetch again later  }
  395.             EmitConstants;     { emit code stack as DB's }
  396.             PrefixBytes := 0; PfxMax := 0;
  397.             HaveAddrPfx := False; HaveSizePfx := False;
  398.         END;
  399.     END; {StowPrefix}
  400.  
  401. BEGIN {HandlePrefix}                {.CP05}
  402.     IF NOT FetchFailure THEN
  403.     IF (ActLvl1[CodeByte].F AND $7) > Ord(CpuAuth) THEN
  404.     BEGIN   EmitConstants; ByteGate := G_ooo END ELSE
  405.     BEGIN
  406.         StowPrefix;
  407.         CodeByte := FetchByte;
  408.         IF NOT FetchFailure
  409.             THEN ByteGate := GateLvl1[CodeByte]
  410.             ELSE ByteGate := G_ooo;
  411.     END;
  412. END; {HandlePrefix}
  413.  
  414.     { -------------------------------------- } {.CP44}
  415.     { Interprets modR/M and optional SIB to  }
  416.     { get operand strings.  Fetches required }
  417.     { displacement fields if any.         }
  418.     { -------------------------------------- }
  419.  
  420. PROCEDURE DecodeModRM(W :WBitStatus);
  421. VAR wmrm : TMrm; wsib : SibRec; wsx : sxRec; Sx : OprStr;
  422. BEGIN
  423.     IF mrmMOD = 3 THEN EAOperand := ExtractReg(AddrMode,W,mrmRM)
  424.     ELSE
  425.     BEGIN
  426.         wmrm     := MrmTab[AddrMode,mrmMOD,mrmRM];
  427.         IF wmrm.SIB = 1 THEN
  428.         BEGIN
  429.             DataByte := FetchByte;
  430.             FormatText(BytesFetched,1,'');
  431.             UnPackSIB(DataByte);
  432.             wsib := SibTab[mrmMOD,sibBAS];
  433.             wsx  := sxTAB[sibSS,sibNDX];
  434.             wmrm.D := wsib.D;
  435.             wmrm.rS := wsib.rS;
  436.             wmrm.rB := wsib.rB;
  437.             wmrm.rX := wsx.rX;
  438.             IF wsx.SF = 0 THEN
  439.             BEGIN
  440.                 NdxSF := '';
  441.                 wmrm.rX := 30     { null register string }
  442.             END
  443.             ELSE NdxSF := '*'+Chr(Ord('0')+wsx.SF);
  444.                 END;
  445.  
  446.         DLoc := FetchDispl(wmrm.D);
  447.         FormatText(DLoc,wmrm.D,'');
  448.         FormatDispl(Sx,DLoc,wmrm.D,True);
  449.         REGSeg   := RegList[wmrm.rS];
  450.         REGBase  := RegList[wmrm.rB];
  451.         REGIndex := RegList[wmrm.rX];
  452.         EAOperand := REGBase;
  453.         IF Length(REGIndex) > 0
  454.         THEN EAOperand := EAOperand + '+' + REGIndex + NdxSF;
  455.         IF wmrm.D > 0 THEN  EAOperand := EAOperand + Sx;
  456.     END;
  457.     REGOperand := ExtractReg(AddrMode,W,mrmREG);
  458. END;
  459.  
  460.     { ---------------------------------- }            {.CP08}
  461.     { Main Driver for 80386 Operand Edit }
  462.     { ---------------------------------- }
  463.  
  464. PROCEDURE Edit386Ops;
  465. VAR
  466.     OpEdit        : TagRec;    Sx    : OprStr;
  467.     i               : Byte;
  468.  
  469.     PROCEDURE EditSplRegs(j : Byte); { CRx,DRx,TRx }    {.CP04}
  470.     BEGIN
  471.         Opnd[j] := OpEdit.A + 'R' + Chr(Ord('0')+mrmREG);
  472.     END;
  473.  
  474.     PROCEDURE EditDblRegs(j : Byte); { EAX..EDI }        {.CP04}
  475.     BEGIN
  476.         Opnd[j] := RegList[16+mrmREG];
  477.     END;
  478.  
  479.     PROCEDURE EditSegRegs(j : Byte); { ES:..GS: }        {.CP04}
  480.     BEGIN
  481.         Opnd[j] := RegList[24+mrmREG];
  482.     END;
  483.  
  484.     PROCEDURE EditLiteral(j : Byte); { literal data }    {.CP04}
  485.     BEGIN
  486.         Opnd[j] := RegList[OpEdit.V];
  487.     END;
  488.  
  489.     PROCEDURE EditGprRegs(j : Byte); { Gb,Gw,Gd,Gv }    {.CP04}
  490.     BEGIN
  491.         Opnd[j] := REGOperand;
  492.     END;
  493.  
  494.     PROCEDURE EditJmpDspl(j : Byte); { Jb, Jv }        {.CP17}
  495.         TYPE
  496.           MyWord = RECORD
  497.         CASE Byte OF
  498.         0: (Ds : ShortInt);
  499.         1: (Db : Byte);
  500.         2: (Dw : Word);
  501.         3: (Di : Integer);
  502.         4: (Dd : LongInt);
  503.         5: (Dv : ARRAY[1..4] OF Byte);
  504.         END;
  505.  
  506.     VAR P : ^MyWord; i,k : Byte; l : LongInt;
  507.     BEGIN
  508.         IF RegList[OpEdit.V][1] = 'b' THEN
  509.         BEGIN
  510.             i := FetchDispl(1);
  511.                         FormatText(i,1,'');
  512.             P := @ CodeStack[i];
  513.             l := CodeOfs + P^.Ds;
  514.             P := @l;
  515.             Opnd[j] := 'SHORT ' + HexB(Hi(P^.Dw))+HexB(Lo(P^.Dw))+'h';
  516.         END ELSE
  517.         BEGIN
  518.             IF ASiz32 THEN k := 4 ELSE k := 2;
  519.             i := FetchDispl(k);        { Displacement }
  520.             FormatText(i,k,'');
  521.                         P := @ CodeStack[i];
  522.                         IF ASiz32
  523.                THEN l := CodeOfs + P^.Dd
  524.                ELSE l := CodeOfs + P^.Di;
  525.             P := @l;
  526.             Opnd[j] := 'h';
  527.             FOR i := 1 TO k DO
  528.                 Opnd[j] := HexB(P^.Dv[i]) + Opnd[j]
  529.         END;
  530.     END;
  531.  
  532.     PROCEDURE EditPointer(j : Byte); { Ap }            {.CP13}
  533.     VAR i,k : Byte;
  534.     BEGIN
  535.         IF ASiz32 THEN k := 4 ELSE k := 2;
  536.         i := FetchDispl(k);            { Displacement }
  537.         FormatText(i,k,'r');
  538.         FormatDispl(Sx,i,k,False);
  539.         k := 2;
  540.         i := FetchDispl(k);            { Selector }
  541.         FormatText(i,k,'s');
  542.         FormatDispl(Opnd[j],i,k,False);
  543.         Opnd[j] := Opnd[j] + ':' + Sx;
  544.     END;
  545.  
  546.     PROCEDURE EditImmData(j : Byte);  { Ib, Iv, Iw }    {.CP17}
  547.     VAR i,k : Byte;
  548.     BEGIN
  549.         CASE RegList[OpEdit.V][1] OF
  550.             'b':    k := 1;
  551.             'w':    k := 2;
  552.             'v':    IF DSiz32 THEN k := 4 ELSE k := 2;
  553.             ELSE    k := 0
  554.         END; {CASE}
  555.         IF k > 0 THEN
  556.         BEGIN
  557.             i := FetchDispl(k);
  558.             FormatText(i,k,'');
  559.             FormatDispl(Sx,i,k,Is_SignXtnd);
  560.             Opnd[j] := Sx;
  561.         END;
  562.     END;
  563.  
  564.     PROCEDURE EditMemAddr(j : Byte);            {.CP04}
  565.     BEGIN
  566.         Opnd[j] := '';
  567.         IF HaveSegPfx   THEN Opnd[j] := REGSegOvr + ': ';
  568.         Opnd[j] := '['+ Opnd[j] + EAOperand + ']';
  569.         HaveMemOprnd := True;
  570.     END;
  571.  
  572.     PROCEDURE EditOfsDspl(j : Byte); { Ob, Ov }        {.CP16}
  573.     VAR i,k : Byte;
  574.     BEGIN
  575.         CASE RegList[OpEdit.V][1] OF
  576.             'b':    k := 2;
  577.             'v':    IF ASiz32 THEN k := 4 ELSE k := 2;
  578.             ELSE    k := 0
  579.         END; {CASE}
  580.         IF k > 0 THEN
  581.         BEGIN
  582.             i := FetchDispl(k);        { Offset }
  583.             FormatText(i,k,'');
  584.             FormatDispl(Sx,i,k,False);
  585.             IF HaveSegPfx AND (mrmMOD <> 3)
  586.                 THEN Sx := REGSegOvr + ': ' + Sx;
  587.             Opnd[j] := '[' + Sx + ']';
  588.             HaveMemOprnd := True;
  589.         END;
  590.     END;
  591.  
  592.     PROCEDURE EditEffAddr(j : Byte); { Eb, Ew, Ev, Ep }    {.CP22}
  593.     BEGIN
  594.         Sx := '';
  595.         IF mrmMOD <> 3 THEN
  596.         IF j = 1 THEN
  597.         CASE RegList[OpEdit.V][1] OF
  598.             'b':    Sx := 'BYTE';
  599.             'w':    Sx := 'WORD';
  600.             'v':    IF DSiz32
  601.                 THEN Sx := 'DWORD'
  602.                 ELSE Sx := 'WORD';
  603.             'p':    IF ASiz32
  604.                 THEN Sx := 'FWORD'
  605.                 ELSE Sx := 'DWORD';
  606.             'q':    Sx := 'QWORD';
  607.             't':    Sx := 'TBYTE';
  608.             'd':    Sx := 'DWORD';
  609.         END; {CASE}
  610.         IF Sx <> '' THEN Sx := Sx + ' PTR ';
  611.         IF HaveSegPfx AND (mrmMOD <> 3)
  612.             THEN Sx := REGSegOvr + ': ' + Sx;
  613.         Opnd[j] := Sx + EAOperand;
  614.         IF mrmMOD <> 3
  615.         THEN BEGIN
  616.             Opnd[j] := '[' + Opnd[j] + ']';
  617.             HaveMemOprnd := True;
  618.              END;
  619.     END;
  620.  
  621.     PROCEDURE EditVarRegs(j : Byte); { eAX..eDI }        {.CP04}
  622.     BEGIN
  623.         Opnd[j] := RegList[OpEdit.V+(Ord(DSiz32) SHL 3)];
  624.     END;
  625.  
  626. BEGIN   {Edit386Ops}                                        {.CP22}
  627.  
  628.     FOR i := 1 TO 3 DO BEGIN
  629.         OpEdit := OpTags[i];
  630.         Opnd[i] := '';
  631.         CASE OpEdit.A OF
  632.             'C',
  633.             'D',
  634.             'T':    EditSplRegs(i);
  635.             'A':    EditPointer(i);
  636.             'R':    EditDblRegs(i);
  637.             'S':    EditSegRegs(i);
  638.             'G':    EditGprRegs(i);
  639.             'J':    EditJmpDspl(i);
  640.             'I':    EditImmData(i);
  641.             'M':    EditMemAddr(i);
  642.             'O':    EditOfsDspl(i);
  643.             'E':    EditEffAddr(i);
  644.             'e':    EditVarRegs(i);
  645.             'r':    EditLiteral(i);
  646.         END; {CASE}
  647.     END;
  648. END; {Edit386Ops}
  649.  
  650. PROCEDURE RemovePrefix;
  651. BEGIN
  652.     WHILE BytesFetched > SPfx DO UnFetchCodeByte;
  653.     IF SPfx <> 1 THEN
  654.     BEGIN
  655.         UnFetchCodeByte;
  656.         EmitConstants;
  657.     END ELSE
  658.     BEGIN
  659.         CodeByte := CodeStack[SPfx];
  660.         CodeText := '';
  661.         FormatText(SPfx,1,'');
  662.         ActGroup := ActLvl1[CodeByte];
  663.         Opnd[1] := '';
  664.         Opnd[2] := '';
  665.         Opnd[3] := '';
  666.         Mnemonic := Mnem386[ActGroup.M];
  667.     END;
  668. END;
  669.  
  670.     { ---------------------------------- } {.CP05}
  671.     { Main Driver for 80386 Instructions }
  672.     { ---------------------------------- }
  673.  
  674. PROCEDURE Handle386Op;
  675. VAR i : Byte; OGate : Gating;
  676.  
  677.     PROCEDURE UpdateTags(n : Byte);
  678.     VAR i : Byte;
  679.     BEGIN
  680.       FOR i := 1 TO 3 DO
  681.         IF OpType386[n,i].A <> ' ' THEN OpTags[i] := OpType386[n,i];
  682.     END;
  683.  
  684.     PROCEDURE HandleOpMRM;                 {.CP17}
  685.     BEGIN
  686.         DataByte := FetchByte;
  687.         IF NOT FetchFailure THEN
  688.         BEGIN
  689.             FormatText(BytesFetched,1,'');
  690.             UnPackModRM(DataByte);
  691.             OGate := ByteGate;
  692.             ByteGate := GateLvl3[ByteGate,mrmREG];
  693.             IF ByteGate = G_Hit THEN
  694.             BEGIN
  695.                 MergeActGrp(ActLvl3[OGate,mrmREG]);
  696.                 UpdateTags(ActGroup.T);
  697.             END;
  698.         END;
  699.     END; {HandleOpMRM}
  700.  
  701.     PROCEDURE HandleOp0Fx;                  {.CP19}
  702.     VAR RowNdx : Gate_2; ColNdx : $0..$F;
  703.     BEGIN
  704.         CodeByte := FetchByte;
  705.         IF NOT FetchFailure THEN
  706.         BEGIN
  707.             FormatText(BytesFetched,1,'');
  708.             RowNdx := GateLvX2[(CodeByte SHR 4) AND $0F];
  709.             ColNdx := CodeByte AND $0F;
  710.             ByteGate := GateLvl2[RowNdx,ColNdx];
  711.             CASE ByteGate OF
  712.                G_Hit: BEGIN
  713.                     MergeActGrp(ActLvl2[RowNdx,ColNdx]);
  714.                     UpdateTags(ActGroup.T);
  715.                   END;
  716.                G_RM6..G_RM8: HandleOpMRM;
  717.             END; {CASE}
  718.         END;
  719.     END; {HandleOp0FX}
  720.  
  721. BEGIN  {Handle386Op}                {.CP34}
  722.     FormatText(BytesFetched,1,'');
  723.     WITH ActLvl1[CodeByte] DO BEGIN
  724.         ActGroup.F := F;
  725.         ActGroup.M := M;
  726.         ActGroup.T := T;
  727.         OpTags := OpType386[ActGroup.T];
  728.     END;
  729.     Case ByteGate OF
  730.         G_RM1..G_RM9:    HandleOpMRM;
  731.         G_0Fx:        HandleOp0Fx;
  732.         G_Hit:;
  733.     END;
  734.     IF (ActGroup.F AND $7) > Ord(CpuAuth) THEN ByteGate := G_ooo;
  735.     IF NOT FetchFailure AND (ByteGate <> G_ooo) THEN
  736.     BEGIN
  737.         Is_386Xtnsn := (ActGroup.F AND _386Xtnsn) = _386Xtnsn;
  738.         Is_32BitMax := (ActGroup.F AND _32BitMax) = _32BitMax;
  739.         Is_16BitMin := (ActGroup.F AND _16BitMin) = _16BitMin;
  740.         Is_SignXtnd := (ActGroup.F AND _SignXtnd) = _SignXtnd;
  741.         Is_MODrmFld := (ActGroup.F AND _MODrmFld) = _MODrmFld;
  742.         IF Is_MODrmFld AND NOT HaveMRM THEN
  743.         BEGIN
  744.             CodeByte := FetchByte;
  745.             IF NOT FetchFailure THEN UnPackModRM(CodeByte);
  746.             FormatText(BytesFetched,1,'');
  747.         END;
  748.         IF Is_32BitMax OR Is_16BitMin THEN WBitMode := W1;
  749.     END;
  750.     IF FetchFailure OR (ByteGate = G_ooo) OR (ActGroup.M = 0)
  751.     THEN EmitConstants ELSE
  752.     BEGIN
  753.         IF DSiz32 AND Is_386Xtnsn
  754.             THEN Mnemonic := Mnem386[ActGroup.M+1]
  755.             ELSE Mnemonic := Mnem386[ActGroup.M];
  756.         IF HaveMRM THEN DecodeModRM(WBitMode);
  757.         Edit386Ops;
  758.         IF HaveSegPfx AND (NOT HaveMemOprnd)
  759.         THEN RemovePrefix ELSE
  760.         BEGIN
  761.             EmuFlag := 0;
  762.             IF (BytesFetched = 2) AND (CodeStack[1] = $CD) THEN
  763.                 CASE CodeStack[2] OF
  764.                     $34..$3B,
  765.                     $3E: BEGIN
  766.                         EmuFlag := CodeStack[2];
  767.                         Opnd[3] := '; F-P Emulator Linkage';
  768.                          END;
  769.                     $3C: BEGIN
  770.                         EmuFlag := CodeStack[2];
  771.                         Opnd[3] := '; Emulated SEG Prefix';
  772.                          END;
  773.                     $3D: Opnd[3] := '; Emulated FWAIT ';
  774.                 END;
  775.         END;
  776.         { emit instruction }
  777.     END;
  778. END; {Handle386Op}
  779.  
  780.     { ----------------------------------------- }        {.CP50}
  781.     { Main driver for Co-Processor Instructions }
  782.     { ----------------------------------------- }
  783.  
  784. PROCEDURE Handle387Op(Emulation : Boolean);
  785. CONST T : ARRAY[2..10] OF Byte = (41,37,39,39,35,40,35,40,41);
  786. VAR esc,flaga,flagop :byte; MpuAux : MpuVec;
  787.     stkr : char;
  788.  
  789. BEGIN
  790.     esc := CodeByte AND $07;
  791.     IF NOT Emulation THEN FormatText(BytesFetched,1,'');
  792.     CodeByte := FetchByte;
  793.     IF NOT FetchFailure THEN UnPackModRM(CodeByte);
  794.     FormatText(BytesFetched,1,'');
  795.     IF mrmMOD = 3 THEN
  796.     BEGIN
  797.         MpuAux   := MpuM11[esc,mrmREG];    {flags,link}
  798.         MpuAux.M := MpuOv[MpuAux.M,mrmRM]  { mnemonic }
  799.     END
  800.     ELSE
  801.         MpuAux   := MpuEA[esc,mrmREG];     {flags,mnemonic}
  802.  
  803.     flaga  := MpuAux.F SHR 4;
  804.     IF flaga = 0 THEN EmitConstants ELSE
  805.     BEGIN
  806.         flagop := MpuAux.F AND $0F;
  807.         stkr   := Chr(Ord('0')+mrmRM);
  808.         CASE flagop OF
  809.              0:     Opnd[1] := '';
  810.              1:     Opnd[1] := 'AX';
  811.              2..10:     BEGIN
  812.                     DecodeModRM(W0);
  813.                     OpTags := OpType386[96];
  814.                     OpTags[1].V := T[flagop];
  815.                     Edit386Ops;
  816.                 END;
  817.             11:     Opnd[1] := 'ST('+stkr+')';
  818.             12:     Opnd[1] := 'ST('+stkr+'),ST';
  819.             13:     Opnd[1] := 'ST,ST('+stkr+')';
  820.         END;
  821.         Mnemonic := Mnem387[MpuAux.M];
  822.         Opnd[2] := '';
  823.         Opnd[3] := '';
  824.         { Emit Instruction Here }
  825.     END;
  826. END; {Handle387Op}
  827.  
  828.     { ----------------------------------------- }     {.CP17}
  829.     { Main Driver for ALL Instruction Sequences }
  830.     { ----------------------------------------- }
  831.  
  832. PROCEDURE HandleInstruction;
  833. BEGIN
  834.     ByteGate := GateLvl1[CodeByte];
  835.     WHILE ByteGate = G_Pfx DO HandlePrefix;
  836.     IF ASiz32 THEN AddrMode := Adr32 ELSE AddrMode := Adr16;
  837.     IF NOT FetchFailure    THEN
  838.         CASE ByteGate OF
  839.             G_RM1..G_0Fx:    Handle386Op;  {Get Op and modR/M}
  840.             G_387:         Handle387Op(False); { Ndp Ops   }
  841.             ELSE        EmitConstants {Invalid Op Codes }
  842.         END;
  843. END;
  844.  
  845.     { -------------------------------- }        {.CP34}
  846.     { Initialize for Instruction Fetch }
  847.     { -------------------------------- }
  848.  
  849. PROCEDURE StartOpFetch; { Initializes for next Instruction }
  850. BEGIN
  851.     Is_386Xtnsn    := False;    Is_32BitMax    := False;
  852.     Is_16BitMin    := False;    Is_SignXtnd     := False;
  853.     Is_MODrmFld     := False;
  854.     HaveSizePfx    := False;    HaveAddrPfx     := False;
  855.     HaveMRM         := False;    HaveSIB        := False;
  856.     FetchFailure    := False;       HaveMemOprnd    := False;
  857.     HaveInstPfx    := False;    HaveSegPfx    := False;
  858.     ASiz32        := SegDBit;    DSiz32        := SegDBit;
  859.  
  860.     CodeByte    := 0;        OprBytes    := 0;
  861.     BytesFetched    := 0;        mrmMOD        := 0;
  862.     mrmREG        := 0;        mrmRM        := 0;
  863.     sibSS        := 0;        sibNDX        := 0;
  864.     sibBAS        := 0;        PfxMax          := 0;
  865.     PrefixBytes    := 0;        DLoc        := 0;
  866.     SPfx        := 0;
  867.  
  868.     CodeText    := '';        NdxSF        := '';
  869.     EAOperand    := '';        REGSeg        := '';
  870.     REGBase        := '';        REGIndex    := '';
  871.     REGOperand    := '';        REGSegOvr    := '';
  872.  
  873.     WBitMode    := W0;        AddrMode    := Adr16;
  874.     ActGroup.F    := 0;        ActGroup.M    := 0;
  875.     ActGroup.T    := 0;           VirtualIP    := CodeOfs;
  876.  
  877.     CodeByte := FetchByte;
  878. END;
  879.  
  880.     { ------------------------------------- }    {.CP11}
  881.     { Prototype For Disassembly of One Line }
  882.     { ------------------------------------- }
  883.  
  884. PROCEDURE DisassembleLine;
  885. BEGIN
  886.     StartOpFetch;
  887.     CASE EmuFlag OF           {Handle Turbo F-P Emulator Expansions}
  888.         $34..$3B : BEGIN
  889.                 UnFetchCodeByte;
  890.                 CodeByte := EmuFlag + $A4;
  891.                 Handle387Op(True);
  892.                 Mnemonic := 'EMU_'+Mnemonic;
  893.                 EmuFlag := 0;
  894.                 Opnd[3] := '; Emulated Operation';
  895.                END;
  896.         $3C:       BEGIN
  897.                 HaveSegPfx := True;
  898.                 REGSegOvr := RegList[24+(CodeByte SHR 6 XOR 3)];
  899.                 Handle387Op(False);
  900.                 Mnemonic := 'EMU_'+Mnemonic;
  901.                 EmuFlag := 0;
  902.                 Opnd[3] := '; Emulated Operation';
  903.                END;
  904.         $3E:       BEGIN  { DB xxH for parameters }
  905.                 EmitConstants;
  906.                 Opnd[3] := '; Fast Path Emulations ';
  907.                 EmuFlag := 0;
  908.                END;
  909.         ELSE BEGIN
  910.             HandleInstruction;
  911.             IF HaveInstPfx
  912.             THEN
  913.               Mnemonic := Mnem386[ActLvl1[IPfx].M] + ' ' + Mnemonic;
  914.              END
  915.     END; {CASE}
  916. END;
  917.  
  918. PROCEDURE UnAssemble(U : UnitHeadPtr; VAR P : ObjArg);
  919. BEGIN
  920.     WITH P DO BEGIN
  921.         IF NOT (TCpu IN [C086..C386]) THEN TCpu := C086;
  922.         CpuAuth := TCpu;
  923.         CodeSeg := Seg(BufPtr(U)^.BufByt[Obj]);
  924.         CodeOfs := Ofs(BufPtr(U)^.BufByt[Obj]);
  925.         BytesRemaining := Lim;
  926.         VirtualIP := Obj;
  927.         Locn := 0;
  928.         Code := '';
  929.         Mnem := '';
  930.         Opr1 := '';
  931.         Opr2 := '';
  932.         Opr3 := '';
  933.     END;
  934.     DisAssembleLine;
  935.     WITH P DO BEGIN
  936.         Obj  := Obj+BytesFetched;
  937.         Lim  := BytesRemaining;
  938.         Code := CodeText;
  939.         Mnem := Mnemonic;
  940.         Opr1 := Opnd[1];
  941.         Opr2 := Opnd[2];
  942.         Opr3 := Opnd[3];
  943.         Locn := VirtualIP;
  944.     END;
  945. END;
  946. BEGIN
  947.     EmuFlag := $0;    {No Borland/Microsoft F-P Emulator in Progress}
  948. END.
  949.